# coding=utf-8

from requests.exceptions import RequestException
from werkzeug.exceptions import NotFound as RawNotFound

from apps.a_common.error.error_code import ER
from apps.a_common.error.exceptions import AppError, InvalidParamError, NetworkError, NotFound
from apps.a_common.response import error_response
from apps.a_common.log import MyLogger

log = MyLogger('error handler')
NETWORK_ERROR_SET = (RequestException, )


def try_get_my_error(e):
    if isinstance(e, NETWORK_ERROR_SET):
        e = NetworkError()

    return e


def exception_handler(e):
    e = try_get_my_error(e)

    if isinstance(e, RawNotFound):
        return error_response(error=NotFound())
    elif isinstance(e, AppError):
        return error_response(error=e, fields=e.fields)
    else:
        log.exception(e)
        return error_response(code=ER.NOT_DEFINED.code, detail="服务错误,请联系我们")


def get_param(params, key, _type, nullable=False, default=None):
    # 获得key 对应的值，处理params为空的情况
    if not params and nullable:
        return default
    val = params.get(key, None)
    log.info(f'get value by key [{key}], need type: [{_type}], get type {type(val)}')

    # 处理值为空的情况
    if (val is None or val == '') and nullable:
        log.info(f'value is None and nullable, return default [{default}]')
        return default
    elif val is None:
        raise InvalidParamError(fields=f"{key} 参数不能为空")

    # 对值做类型处理
    log.info('has value, try to check type')
    try:
        # 对bool做特殊判断
        if _type == bool and isinstance(val, str) and val.lower() == 'false':
            result = False
        else:
            result = _type(val)
    except ValueError as e:
        log.info('param type error, detail: {}, {}, {}'.format(type(e), e, e.args))
        raise InvalidParamError(fields=f"{key} 参数类型错误")
    except Exception as e:
        log.info('param error, detail: {}, {}'.format(type(e), e, e.args))
        raise InvalidParamError(fields=f"{key} 参数错误")
    else:
        return result

    raise Exception()
